package com.heima.comment.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.heima.comment.service.CommentHotService;
import com.heima.comment.service.CommentService;
import com.heima.common.constants.article.HotArticleConstants;
import com.heima.common.constants.message.UpdateArticleMess;
import com.heima.common.exception.CustException;
import com.heima.feigns.UserFeign;
import com.heima.model.comment.dtos.CommentDTO;
import com.heima.model.comment.dtos.CommentLikeDTO;
import com.heima.model.comment.dtos.CommentSaveDTO;
import com.heima.model.comment.pojos.ApComment;
import com.heima.model.comment.pojos.ApCommentLike;
import com.heima.model.comment.vos.ApCommentVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.threadlocal.AppThreadLocalUtils;
import com.heima.model.user.pojos.ApUser;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CommentServiceImpl implements CommentService {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private UserFeign userFeign;

    @Autowired
    RedissonClient redissonClient;

    @Autowired
    CommentHotService commentHotService;
    @Autowired
    RabbitTemplate rabbitTemplate;

    /**
     * 保存/发表评论
     * @param dto
     * @return
     */
    @Override
    public ResponseResult saveComment(CommentSaveDTO dto) {
        //TODO 1 参数校验
        //todo 判断是否登录
        ApUser user = AppThreadLocalUtils.getUser();
        if (user==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN,"只有登录后才能发表评论");
        }
        //TODO 2 阿里云文本检测

        //TODO 4 保存评论信息
        ResponseResult<ApUser> apUserResult = userFeign.findUserById(user.getId());
        if (apUserResult.getCode()!=0||apUserResult.getData()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE,"当前登录信息有误");
        }
        user = apUserResult.getData();
        ApComment apComment = new ApComment();

        apComment.setAuthorId(user.getId());
        apComment.setAuthorName(user.getName());
        apComment.setArticleId(dto.getArticleId());
        apComment.setType((short)0);
        apComment.setContent(dto.getContent());
        apComment.setImage(user.getImage());
        apComment.setLikes(0);
        apComment.setReply(0);
        apComment.setFlag((short)0);
        apComment.setCreatedTime(new Date());
        apComment.setUpdatedTime(new Date());

        mongoTemplate.save(apComment);


        //TODO ***********评论行为MQ*****************
        UpdateArticleMess updateArticleMess = new UpdateArticleMess();
        updateArticleMess.setType(UpdateArticleMess.UpdateArticleType.COMMENT);
        updateArticleMess.setArticleId(dto.getArticleId());
        updateArticleMess.setAdd(1);
        rabbitTemplate.convertAndSend(HotArticleConstants.HOT_ARTICLE_SCORE_BEHAVIOR_QUEUE,
                JSON.toJSONString(updateArticleMess));
        log.info("评论行为 发送消息 ==>{}",updateArticleMess);
        return ResponseResult.okResult();
    }

    /**
     * 保存评论点赞
     * @param dto
     * @return
     */
    @Override
    public ResponseResult like(CommentLikeDTO dto) {
        //TODO 检查参数
        //todo 判断用户是否登录
        ApUser user = AppThreadLocalUtils.getUser();
        if (user==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN,"请先登录");
        }

        //TODO 异步线程池操作--加锁
        RLock likesLock = redissonClient.getLock("likesLock");
        likesLock.lock();
        ApComment apComment;

        try {
            //TODO 根据评论id查询评论信息
            apComment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
            if (apComment==null){
                log.error("没有查询到评论信息，评论id:{}",dto.getCommentId());
                return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"没有查询到评论信息");
            }
            //todo 用户不能重复点赞
            Short operation = dto.getOperation();
            Query query = Query.query(Criteria.where("authorId").is(user.getId())
                    .and("commentId").is(dto.getCommentId()));

            ApCommentLike apCommentLike = mongoTemplate.findOne(query, ApCommentLike.class);
            if (operation.intValue()==0&&apCommentLike!=null){
                CustException.cust(AppHttpCodeEnum.DATA_EXIST,"你已点赞，请不要重复点赞");
            }
            if (operation.intValue()==0){
                //todo 点赞+1 用户点赞增加点赞数量，并记录当前用户对于当前评论的数据记录
                apComment.setLikes(apComment.getLikes()+1);
                mongoTemplate.save(apComment);


                //保存评论点赞信息
                apCommentLike = new ApCommentLike();
                apCommentLike.setAuthorId(user.getId());//评论的用户ID（当前登录人ID  apUserId）
                apCommentLike.setCommentId(apComment.getId());
                apCommentLike.setOperation(dto.getOperation());
                mongoTemplate.save(apCommentLike);

                //查看是否是热点评论
                if (apComment.getLikes()>=10&&apComment.getFlag().intValue()==0){
                    System.out.println(Thread.currentThread().getName());
                    commentHotService.hotCommentExecutor(apComment);
                }

            }else {
                //取消点赞
                apComment.setLikes(apComment.getLikes()<=0 ? 0:apComment.getLikes()-1);
                mongoTemplate.save(apComment);
                //删除评论点赞信息
                Query query1 = Query.query(Criteria.where("authorId").is(user.getId())
                        .and("commentId").is(apComment.getId()));
                mongoTemplate.remove(query1,ApCommentLike.class);
            }
        } finally {
            likesLock.unlock(); // 释放锁
        }
        //todo 数据返回 返回点赞数量
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("likes",apComment.getLikes());
        return ResponseResult.okResult(resultMap);
    }

    /**
     * 加载评论列表
     * @param dto
     * @return
     */
    @Override
    public ResponseResult loadComment(CommentDTO dto) {
        //TODO 检查参数(文章id 最小时间 分页10条)
        if (dto==null||dto.getArticleId()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        Integer size = dto.getSize();
        if (size==null||size<=0){
            dto.setSize(10);
        }
        //TODO 查询mongo中所有评论列表
        List<ApComment> apCommentList=null;
//        //TODO 查询文章所有评论数据
//        Query query = Query.query(Criteria.where("articleId").is(dto.getArticleId()).
//                and("createdTime").lt(dto.getMinDate()))
//                .limit(dto.getSize())
//                .with(Sort.by(Sort.Direction.DESC, "createdTime"));
//        List<ApComment> apCommentList = mongoTemplate.find(query, ApComment.class);

        // 首页评论查询
        if (dto.getIndex().intValue()==1){
            apCommentList=mongoTemplate.find(
                    Query.query(Criteria.where("articleId").is(dto.getArticleId())
                    .and("flag").is(1))
                    .with(Sort.by(Sort.Direction.DESC,"likes")),
                    ApComment.class);

            if (CollectionUtils.isNotEmpty(apCommentList)){
                // 要查询普通评论的数量
                size=dto.getSize()-apCommentList.size();
                List<ApComment> normalList = mongoTemplate.find(
                        Query.query(Criteria.where("articleId").is(dto.getArticleId())
                                .and("createdTime").lt(dto.getMinDate())
                                .and("flag").is(0))
                                .limit(size)
                                .with(Sort.by(Sort.Direction.DESC, "createdTime"))
                        , ApComment.class);
                apCommentList.addAll(normalList);

            }else {
                apCommentList = mongoTemplate.find(
                        Query.query(Criteria.where("articleId").is(dto.getArticleId())
                                .and("createdTime").lt(dto.getMinDate()).and("flag").is(0))
                                .limit(dto.getSize())
                                .with(Sort.by(Sort.Direction.DESC,"createdTime")),
                        ApComment.class
                );
            }
        }else { // 查询更多 普通 评论
            apCommentList = mongoTemplate.find(
                    Query.query(Criteria.where("articleId").is(dto.getArticleId())
                            .and("createdTime").lt(dto.getMinDate()).and("flag").is(0))
                            .limit(dto.getSize())
                            .with(Sort.by(Sort.Direction.DESC, "createdTime")),
                    ApComment.class
            );
        }
        //3 封装查询结果
        //todo 判断用户是否登录，未登录直接返回评论列表
        ApUser user = AppThreadLocalUtils.getUser();
        if (user==null){
            return ResponseResult.okResult(apCommentList);
        }
        //TODO 如果用户登录判断自己是否点过赞
        ArrayList<ApCommentVo> apCommentVoList = new ArrayList<>();
        //todo 获取文章对应的所有评论ID列表
        List<String> idList = apCommentList.stream()
                .map(comment -> comment.getId()).collect(Collectors.toList());
        // 查询 点赞批量列表 按照评论id 筛选
        Query query1 = Query.query(Criteria.where("commentId")
                .in(idList)
                .and("authorId").is(user.getId()));
        List<ApCommentLike> apCommentLikes = mongoTemplate.find(
                query1, ApCommentLike.class);



        // 遍历当前用户点赞列表 和当前评论列表
        if (CollectionUtils.isNotEmpty(apCommentList) &&
                CollectionUtils.isNotEmpty(apCommentLikes)){
            apCommentList.forEach(comment->{
                ApCommentVo apCommentVo = new ApCommentVo();
                BeanUtils.copyProperties(comment,apCommentVo);
                //遍历当前用户点赞列表
                apCommentLikes.forEach(apCommentLike -> {
                    // 文章评论列表id 和 当前用户点赞评论列表id是否相等
                    if (comment.getId().equals(apCommentLike.getCommentId())){
                        apCommentVo.setOperation((short)0);
                    }
                });
                apCommentVoList.add(apCommentVo);
            });
            return ResponseResult.okResult(apCommentVoList);
        }
        //todo ApCommentVO+operation(0)根据点赞情况修改对应评论数据的operation字段
        //TODO 返回数据
        return ResponseResult.okResult(apCommentList);
    }



}
